package org.xxpay.pay.channel.dwf;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.xxpay.common.http.HttpRequestTemplate;
import org.xxpay.common.util.DateUtils;
import org.xxpay.common.util.HtmlUtils;
import org.xxpay.common.util.sign.SignUtils;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.JsonUtil;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayment;
import org.xxpay.pay.channel.dwf.util.EncodeUtil;

import java.util.Date;
import java.util.Map;

@Service
public class DwfPaymentService extends BasePayment {

    private final static String logPrefix = "【DWF】";

    private final static String QUICK_ORDER_URL = "/102001.pay";

    private final static String QUICK_ORDER_QUERY_URL = "/102010.pay";

    @Override
    public String getChannelName() {
        return DwfConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        switch (channelId) {
            case DwfConfig.CHANNEL_NAME_DWF_QUICK:
                return doOrderQuick(payOrder);
            default:
                return buildRetObj(PayConstant.RETURN_VALUE_FAIL, "不支持的渠道[channelId="+channelId+"]");
        }
    }

    @Override
    public JSONObject query(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        switch (channelId) {
            case DwfConfig.CHANNEL_NAME_DWF_QUICK:
                return doOrderQuickQuery(payOrder);
            default:
                return buildRetObj(PayConstant.RETURN_VALUE_FAIL, "不支持的渠道[channelId="+channelId+"]");
        }
    }

    private JSONObject doOrderQuick(PayOrder payOrder) {
        DwfConfig dwfConfig = new DwfConfig(getPayParam(payOrder));
        Map<String, Object> paramMap = Maps.newHashMap();
        setQuickParam(paramMap, payOrder, dwfConfig);
        String encryptData = getEncryptData(paramMap, dwfConfig);
        String sign = getSign(paramMap, dwfConfig);

        rpcCommonService.rpcPayOrderService.updateStatus4Ing(payOrder.getPayOrderId(), null);

        Map<String, Object> reqMap = Maps.newHashMap();
        reqMap.put("encryptData", encryptData);
        reqMap.put("partnerNo", dwfConfig.getMchId());
        reqMap.put("signData", sign);

        String form = HtmlUtils.form(getReqUrl(dwfConfig.getRequestUrl(), QUICK_ORDER_URL), reqMap);

        JSONObject retObj = new JSONObject();

        retObj.put("payOrderId", payOrder.getPayOrderId());
        JSONObject payInfo = new JSONObject();
        payInfo.put("payUrl",form);
        payInfo.put("payMethod",PayConstant.PAY_METHOD_FORM_JUMP);
        retObj.put("payParams", payInfo);
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_SUCCESS);
        return retObj;
    }
    private JSONObject doOrderQuickQuery(PayOrder payOrder) {
        DwfConfig dwfConfig = new DwfConfig(getPayParam(payOrder));
        Map<String, Object> paramMap = Maps.newHashMap();
        setQuickQueryParam(paramMap, payOrder, dwfConfig);
        String encryptData = getEncryptData(paramMap, dwfConfig);
        String sign = getSign(paramMap, dwfConfig);
        Map<String, Object> reqMap = Maps.newHashMap();
        reqMap.put("partnerNo", dwfConfig.getMchId());
        reqMap.put("encryptData", encryptData);
        reqMap.put("signData", sign);

        _log.info("{}查询订单下单请求参数：{}", logPrefix, JSONObject.toJSONString(reqMap));
        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(null);
        String origin = requestTemplate.postForObject(getReqUrl(dwfConfig.getRequestUrl(), QUICK_ORDER_QUERY_URL), reqMap, String.class);
        JSONObject resObject = JsonUtil.getObjectFromJson(origin, JSONObject.class);
        String resEncryptData = resObject.getString("encryptData");
        String privateKey = dwfConfig.getPrivateKey();
        String plainText = EncodeUtil.decode(resEncryptData, privateKey.substring(0, 16));
        _log.info("{}请求响应参数：{}", logPrefix, plainText);
        JSONObject resData = JsonUtil.getJSONObjectFromJson(plainText);
        JSONObject retObj = new JSONObject();

        String orderStatus = resData.getString("orderStatus");
        if(StringUtils.equals(orderStatus, "01")) {
            retObj.put("status", 2); // 已支付
        } else if(StringUtils.equals(orderStatus, "04")) {
            retObj.put("status", 1); // 支付中
        }
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_SUCCESS);
        retObj.put("channelOrderNo", resData.getString("oriPlatformId"));
        retObj.put("channelObj", resData);
        return retObj;
    }

    private void setQuickParam(Map<String, Object> params, PayOrder payOrder, DwfConfig dwfConfig) {
        params.put("payAmount", payOrder.getAmount().toString());
        params.put("productName", payOrder.getSubject());
        params.put("productDesc", payOrder.getBody());
        params.put("callBackUrl", payConfig.getNotifyUrl(getChannelName()));
        params.put("frontUrl", payOrder.getReturnUrl());
        params.put("channelType", "01");
        Map<String, Object> head = getCommonParam(payOrder, dwfConfig, "102001");
        params.put("head", head);
    }

    private void setQuickQueryParam(Map<String, Object> params, PayOrder payOrder, DwfConfig dwfConfig) {
        params.put("oriTraceId", payOrder.getPayOrderId());
        Map<String, Object> head = getCommonParam(payOrder, dwfConfig, "102001");
        params.put("head", head);
    }

    private Map<String, Object> getCommonParam(PayOrder payOrder,DwfConfig dwfConfig, String txnCode){
        Map<String, Object> params = Maps.newHashMap();
        params.put("version", "1.0.0");
        params.put("charset", SignUtils.CHARSET_UTF8);
        params.put("partnerNo", dwfConfig.getMchId());
        params.put("partnerType", "OUTER");
        params.put("txnCode", txnCode);
        params.put("traceId", payOrder.getPayOrderId());
        Date now = new Date();
        params.put("reqDate", DateUtils.YYYYMMDD.format(now));
        params.put("reqTime", DateUtils.YYYYMMDDHHMMSS.format(now));
        return params;
    }

    private String getEncryptData(Map<String, Object> params, DwfConfig dwfConfig) {
        String aesKey = dwfConfig.getPrivateKey().substring(0, 16);
        String planText = JsonUtil.object2Json(params);
        _log.info("{}请求参数：{}", logPrefix, planText);
        return EncodeUtil.encode(planText, aesKey);
    }

    private String getSign(Map<String, Object> params, DwfConfig dwfConfig) {
        String sha1Key = dwfConfig.getPrivateKey().substring(16);
        String jsonBody = JsonUtil.object2Json(params);
        return DigestUtils.sha1Hex(jsonBody+sha1Key);
    }

}
